page	80,128
title	PLAYINT.ASM	3/27/85	bjs

include		GENERAL.EQU
include		PLAYINT.EQU
include		PCIO.EQU
include		SOUND.EQU
include		PHASER.EQU
include		PLANET.EQU

ACCEL_SCALE		EQU	3
LOW_SHIELD_LIMIT	EQU	16

PUBLIC	Play_Interrupt

PUBLIC	PLANET_ENABLE
PUBLIC	PLANET_STATE

EXTRN	Cos:near				; in sin.asm
EXTRN	Sin:near				; in sin.asm
EXTRN	Update_Gravity:near			; in gravity.asm
EXTRN	Xor_Left_S:near				; in draw.asm
EXTRN	Xor_Right_S:near			; in draw.asm
EXTRN	Sound:near				; in sound.asm
EXTRN	Draw_The_Planet:near			; in draw.asm
EXTRN	Pixel:near				; in draw.asm

EXTRN	BLINK:byte
EXTRN	SOUND_FLAG:byte
EXTRN	LETTER_FLAG:byte
EXTRN	HYPER_ENT_FLAG:byte
EXTRN	HYPER_KLN_FLAG:byte
EXTRN	PAUSE_ENABLE:byte

EXTRN	XDISL:word
EXTRN	XDIS:word
EXTRN	YDISL:word
EXTRN	YDIS:word
EXTRN	XVELL:word
EXTRN	XVEL:word
EXTRN	YVELL:word
EXTRN	YVEL:word
EXTRN	XDRAWN:word
EXTRN	YDRAWN:word
EXTRN	ADRAWN:word
EXTRN	UFLG:word
EXTRN	EFLG:word
EXTRN	ANGLE:word
EXTRN	ROTATE:word
EXTRN	FLAGS:word
EXTRN	ENRGY:word
EXTRN	SHLDS:word
EXTRN	PHST:word
EXTRN	TITLE_X_VEL:word
EXTRN	TITLE_Y_VEL:word
EXTRN	TITLE_X_DIS:word
EXTRN	TITLE_Y_DIS:word
EXTRN	TITLE_X_DISL:word
EXTRN	TITLE_Y_DISL:word
EXTRN	DOT_SEG:word


pc_time		STRUC
	DUMMY		DB	06CH DUP(?)
	TIMER_LOW	DW	?
	TIMER_HIGH	DW	?
	TIMER_OFL	DB	?
pc_time		ENDS

space_data	segment	public	'space_data'

PLANET_ENABLE	DB	0			; IF =1 DRAW PLANET
PLANET_STATE	DB	0			; WHICH OF SIXTEEN PICTURES

space_data	ends

space_code	segment	public	'space_code'

PAGE
;--- MODULE:	scalx/scaly	--------------------------------
; Entry
;	bl = angle
; Exit
;	ax = lo acceleration
;	dx = hi acceleration
; Affects
;	Register	ax,bx,dx
; Function
;	1. Scaled acceleration
;--- Revision History
;	12/19/84	bjs
;---------------------------------------------------------------
	ASSUME	CS:space_code,DS:space_data,ES:Nothing

scalx	proc	near

	call	Cos
	jmp	scy100
scaly:
	call	Sin
scy100:
	cwd					; sign extend
	push	cx
	mov	cx,ACCEL_SCALE
scy200:
	sar	dx,1
	rcr	ax,1
	loop	scy200
	pop	cx
	ret

scalx	endp

PAGE
;--- MODULE:	update	----------------------------------------
; Entry
;	si = object #
; Exit
;	NONE
; Affects
;	Register	ax,bx,cx,dx
;			XDIS,YDIS,XDISL,YDISL
; Function
;	1. Update position of moving objects.
;--- Revision History
;	12/19/84	bjs
;---------------------------------------------------------------
	ASSUME	CS:space_code,DS:space_data,ES:Nothing

update	proc	near

	mov	ax,XVELL[si]			; velocity low word
	mov	dx,XVEL[si]			; velocity high word
	add	XDISL[si],ax			; accum x displacement
	adc	dx,XDIS[si]
	jns	updt100
	add	dx,MAX_X_AXIS			; underflow
updt100:
	cmp	dx,WRAP_FACTOR
	jnb	updt200
	add	dx,MAX_X_AXIS-(2*WRAP_FACTOR)
	jmp	updt300
updt200:
	cmp	dx,MAX_X_AXIS-WRAP_FACTOR	; wrap over ?
	jb	updt300
	sub	dx,MAX_X_AXIS-(2*WRAP_FACTOR)
updt300:
	mov	XDIS[si],dx
	cmp	dx,XDRAWN[si]			; did it move ?
	je	updt400				; no - dont draw
	or	byte ptr UFLG[SI],BIT0		; yes - set update flag
updt400:
	mov	ax,YVELL[si]			; velocity low word
	mov	dx,YVEL[si]			; velocity high word
	add	YDISL[si],ax			; accum y displacement
	adc	dx,YDIS[si]
	jns	updt500
	add	dx,MAX_Y_AXIS			; underflow
updt500:
	cmp	dx,WRAP_FACTOR
	jnb	updt600
	add	dx,MAX_Y_AXIS-(2*WRAP_FACTOR)
	jmp	updt700
updt600:
	cmp	dx,MAX_Y_AXIS-WRAP_FACTOR	; wrap over ?
	jb	updt700
	sub	dx,MAX_Y_AXIS-(2*WRAP_FACTOR)
updt700:
	mov	YDIS[si],dx
	cmp	dx,YDRAWN[si]			; change in position ?
	je	updt800				; no - dont draw
	or	byte ptr UFLG[si],BIT0		; set update flag
updt800:
	ret

update	endp

PAGE
;--- MODULE:	Play_Interrupt	--------------------------------
; Entry
;	NONE
; Exit
;	NONE
; Affects
;	NONE
; Function
;	1. Update positions and draw ships
;	2. System Timer 3 interrupt handler.
;--- Revision History
;	12/19/84	bjs
;---------------------------------------------------------------
	ASSUME	CS:space_code,DS:Nothing,ES:Nothing

Play_Interrupt	proc	near

	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di
	push	bp
	push	ds
	push	es

	mov	ax,space_data
	mov	ds,ax
	ASSUME	DS:space_data

	inc	BLINK				; game state ctr

	test	BLINK,3				; time to update sys clock
	jne	psys_t5				; no
	mov	ax,040H
	mov	es,ax
	inc	ES:TIMER_LOW
	jnz	psys_t4
	inc	ES:TIMER_HIGH
psys_t4:
	cmp	ES:TIMER_HIGH,018H		; 24 hours ?
	jnz	psys_t5				; no
	cmp	ES:TIMER_LOW,0B0H		; maybe - check low
	jnz	psys_t5				; no
	xor	ax,ax				; timer overflow zero
	mov	ES:TIMER_LOW,ax
	mov	ES:TIMER_HIGH,ax
	mov	ES:TIMER_OFL,1			; flag overflow
psys_t5:
	test	PAUSE_ENABLE,BIT0		; in a pause state ?
	je	psys_t6				; no
	jmp	ihypk950			; yes - skip all this

psys_t6:
	test	EFLG+ENTOBJ,0FFH		; enterprise enabled ?
	je	ref100				; no
	mov	al,byte ptr ANGLE+ENTOBJ
	add	al,byte ptr ROTATE+ENTOBJ
	mov	byte ptr ANGLE+ENTOBJ,al
	test	byte ptr FLAGS+ENTOBJ,BIT0	; thrusting ?
	je	ref070				; no - leave velocity
	mov	al,BLINK			; yes - use energy 1/4 time
	and	al,IMPULSE_TIME-1
	jne	ref050
	dec	byte ptr ENRGY+ENTOBJ
	je	ref100				; no action if zero energy
ref050:
	mov	bl,byte ptr ANGLE+ENTOBJ	; update ent x velocity
	call	scalx				; get x part of accel.
	add	XVELL+ENTOBJ,ax
	adc	dx,XVEL+ENTOBJ
	mov	ax,dx
	or	ax,ax				; make positive
	jns	ref055
	neg	ax
ref055:
	cmp	ax,MAX_X_VELOCITY
	jnb	ref060
	mov	XVEL+ENTOBJ,dx
ref060:
	mov	bl,byte ptr ANGLE+ENTOBJ	; update ent y velocity
	call	scaly
	add	YVELL+ENTOBJ,ax
	adc	dx,YVEL+ENTOBJ
	mov	ax,dx
	or	ax,ax				; make positive
	jns	ref065
	neg	ax
ref065:
	cmp	ax,MAX_Y_VELOCITY
	jnb	ref070
	mov	YVEL+ENTOBJ,dx
ref070:
	test	byte ptr FLAGS+ENTOBJ,BIT1	; cloaking ?
	je	ref100				; no
	mov	al,BLINK			; yes - use energy 1/4 time
	and	al,CLOAK_TIME-1
	jne	ref100
	dec	byte ptr ENRGY+ENTOBJ
ref100:
	test	EFLG+KLNOBJ,0FFH		; klingon enabled ?
	je	ref200				; no
	mov	al,byte ptr ANGLE+KLNOBJ
	add	al,byte ptr ROTATE+KLNOBJ
	mov	byte ptr ANGLE+KLNOBJ,al
ref140:
	test	byte ptr FLAGS+KLNOBJ,BIT0	; thrusting ?
	je	ref180				; no - leave velocity
	mov	al,BLINK			; yes - use energy 1/4 time
	and	al,IMPULSE_TIME-1
	jne	ref160
	dec	byte ptr ENRGY+KLNOBJ
	je	ref200				; no action if zero energy
ref160:
	mov	bl,byte ptr ANGLE+KLNOBJ	; update kln x velocity
	call	scalx				; get x part of accel.
	add	XVELL+KLNOBJ,ax
	adc	dx,XVEL+KLNOBJ
	mov	ax,dx
	or	ax,ax				; make positive
	jns	ref165
	neg	ax
ref165:
	cmp	ax,MAX_X_VELOCITY
	jnb	ref170
	mov	XVEL+KLNOBJ,dx
ref170:
	mov	bl,byte ptr ANGLE+KLNOBJ	; update kln y velocity
	call	scaly
	add	YVELL+KLNOBJ,ax
	adc	dx,YVEL+KLNOBJ
	mov	ax,dx
	or	ax,ax				; make positive
	jns	ref175
	neg	ax
ref175:
	cmp	ax,MAX_X_VELOCITY
	jnb	ref180
	mov	YVEL+KLNOBJ,dx
ref180:
	test	byte ptr FLAGS+KLNOBJ,BIT1	; cloaking ?
	je	ref200				; no
	mov	al,BLINK			; yes - use energy 1/4 time
	and	al,CLOAK_TIME-1
	jne	ref200
	dec	byte ptr ENRGY+KLNOBJ
ref200:

;	****** UPDATE SHIPS AND TORPS ******

	mov	si,ENTOBJ-2			; first object
udt300:
	inc	si
	inc	si
	cmp	si,ENDOBJ			; at last object yet ?
	jnb	udt400
	test	byte ptr EFLG[si],0FFH		; is torp fired ?
	je	udt300				; no
	js	udt300				; no - exploding
	call	update				; yes - update its position
	test	PLANET_ENABLE,BIT1		; gravity on ?
	je	udt300				; no
	call	Update_Gravity
	jmp	udt300
udt400:

;	****** ENERGY UPDATE ******

	mov	al,BLINK			; time to blink off ?
	and	al,WARNING_TIME-1
	jne	eng160				; no
	and	SOUND_FLAG,NOT WARNING_SOUND	; warning sound off
	test	byte ptr EFLG+ENTOBJ,0FFH	; enterprise active ?
	je	eng120				; no
	js	eng120
	mov	al,byte ptr SHLDS+ENTOBJ	; ent shields lo ?
	cmp	al,LOW_SHIELD_LIMIT
	jb	eng100				; yes
	test	LETTER_FLAG,BIT0		; no - left s on screen ?
	je	eng110				; no
	jmp	eng120
eng100:
	or	SOUND_FLAG,WARNING_SOUND	; warning sound on
eng110:
	call	Xor_Left_S			; leave left s
eng120:
	test	byte ptr EFLG+ENTOBJ,0FFH	; klingon active ?	
	je	eng160				; no
	js	eng160
	mov	al,byte ptr SHLDS+KLNOBJ	; kln shields lo ?
	cmp	al,LOW_SHIELD_LIMIT
	jb	eng140				; yes
	test	LETTER_FLAG,BIT1		; no - rigth s on screen ?
	je	eng150				; no
	jmp	eng160
eng140:
	or	SOUND_FLAG,WARNING_SOUND	; warning sound on
eng150:
	call	Xor_Right_S			; leave right s
eng160:
	mov	al,BLINK			; dilithium crystals recharge
	and	al,DILITHIUM_TIME-1
	jne	eng500				; no
	mov	al,byte ptr ENRGY+ENTOBJ
	or	al,al				; no recharge if zero energy
	je	eng400
	inc	al
	js	eng400
	mov	byte ptr ENRGY+ENTOBJ,al
eng400:
	mov	al,byte ptr ENRGY+KLNOBJ
	or	al,al				; no recharge if zero energy
	je	eng500
	inc	al
	js	eng500
	mov	byte ptr ENRGY+KLNOBJ,al
eng500:

;	****** PHOTON ENERGY LOSS ******

	mov	al,BLINK			; time to lose torp energy
	and	al,PHOTON_TIME-1
	jne	phl500				; no
	mov	si,ENTTORP0			; first enterprise torp
phl100:
	test	byte ptr EFLG[si],0FFH		; is torp fired ?
	je	phl200				; no
	js	phl200				; exploding
	mov	al,byte ptr ENRGY[si]
	or	al,al				; any energy left
	je	phl200				; no
	dec	byte ptr ENRGY[si]		; loss of energy
phl200:
	inc	si
	inc	si
	cmp	si,KLNOBJ			; at last enterprise torp ?
	jb	phl100				; no
	mov	si,KLNTORP0			; first klingon torp
phl300:
	test	byte ptr EFLG[si],0FFH		; is torp fired ?
	je	phl400				; no
	js	phl400				; exploding
	mov	al,byte ptr ENRGY[si]
	or	al,al				; any energy left
	je	phl400				; no
	dec	byte ptr ENRGY[si]		; loss of energy
phl400:
	inc	si
	inc	si
	cmp	si,ENDOBJ			; at last klingon torp ?
	jb	phl300				; no
phl500:

;	****** DEC PHASER STATE CTR ******

	mov	al,byte ptr PHST+ENTOBJ		; done ent phaser ?
	or	al,al
	js	pst100				; yes
	cmp	al,PHASER_ERASE			; erase flag ?
	je	pst100				; yes - erase will dec
	dec	byte ptr PHST+ENTOBJ
pst100:
	mov	al,byte ptr PHST+KLNOBJ		; done kln phaser ?
	or	al,al
	js	pst200				; yes
	cmp	al,PHASER_ERASE			; erase flag ?
	je	pst200
	dec	byte ptr PHST+KLNOBJ
pst200:

	call	Sound				; udate sounds

; ****************** HYPERSPACE ENTERPRISE ******************

	mov	al,HYPER_ENT_FLAG		; enterprise in hyperspace ?
	or	al,al
	jne	ihype050			; yes
	jmp	ihype950			; no

ihype050:
	mov	es,DOT_SEG
	inc	HYPER_ENT_FLAG
	cmp	al,32				; half way done ?
	jne	ihype300
	mov	si,0
	mov	cx,32
ihype100:
	neg	TITLE_X_VEL[si]			; cause drift toward final destination
	neg	TITLE_Y_VEL[si]
	inc	si
	inc	si
	loop	ihype100
	jmp	ihype320

ihype300:
	cmp	al,64				; fully done ?
	jne	ihype320			; no
	jmp	ihype900			; yes

ihype320:
	mov	si,0
	mov	cx,32
ihype400:
	mov	bx,TITLE_X_DIS[si]		; erase old pixel
	mov	dx,TITLE_Y_DIS[si]
	call	Pixel

	mov	ax,TITLE_X_VEL[si]		; calc new pixel position
	cwd
	shl	ax,1
	rcl	dx,1				; scale up by two
	add	ax,XVELL+ENTOBJ			; make total velocity
	adc	dx,XVEL+ENTOBJ

	add	TITLE_X_DISL[si],ax
	adc	dx,TITLE_X_DIS[si]
	jns	ihype410			; screen wrap
	add	dx,MAX_X_AXIS
	jmp	ihype420
ihype410:
	cmp	dx,MAX_X_AXIS
	jb	ihype420
	sub	dx,MAX_X_AXIS
ihype420:
	mov	TITLE_X_DIS[si],dx
	mov	bx,dx				; for draw pixel later

	mov	ax,TITLE_Y_VEL[si]		; calc new pixel position
	cwd
	shl	ax,1
	rcl	dx,1				; scale up by two
	shl	ax,1
	rcl	dx,1				; scale up by two
	add	ax,YVELL+ENTOBJ			; make total velocity
	adc	dx,YVEL+ENTOBJ

	add	TITLE_Y_DISL[si],ax
	adc	dx,TITLE_Y_DIS[si]
	jns	ihype510			; screen wrap
	add	dx,MAX_Y_AXIS
	jmp	ihype520
ihype510:
	cmp	dx,MAX_Y_AXIS
	jb	ihype520
	sub	dx,MAX_Y_AXIS
ihype520:
	mov	TITLE_Y_DIS[si],dx
	call	Pixel				; draw pixel in new position
	inc	si
	inc	si
	loop	ihype400

	jmp	ihype950

ihype900:					; done with hyperspace
	mov	si,0
	mov	cx,32
ihype930:
	mov	bx,TITLE_X_DIS[si]		; erase all pixels
	mov	dx,TITLE_Y_DIS[si]
	call	Pixel
	inc	si
	inc	si
	loop	ihype930

	mov	HYPER_ENT_FLAG,0		; stop hyperspace
	or	byte ptr UFLG+ENTOBJ,BIT0	; flag for an update
	or	byte ptr EFLG+ENTOBJ,BIT0	; enable enterprise should draw it
	mov	ax,TITLE_X_DIS
	mov	XDIS+ENTOBJ,ax
	mov	XDRAWN+ENTOBJ,ax		; new position
	mov	ax,TITLE_Y_DIS
	mov	YDIS+ENTOBJ,ax
	mov	YDRAWN+ENTOBJ,ax
	xor	ax,ax
	mov	XVEL+ENTOBJ,ax			; stop enterprise
	mov	XVELL+ENTOBJ,ax
	mov	YVEL+ENTOBJ,ax
	mov	YVELL+ENTOBJ,ax
	mov	XDISL+ENTOBJ,ax
	mov	YDISL+ENTOBJ,ax

	and	SOUND_FLAG,NOT HYPER_SOUND	; stop sound
ihype950:					; no hyperspace	for enterprise

; ****************** HYPERSPACE KLINGON ******************

	mov	al,HYPER_KLN_FLAG		; klingon in hyperspace ?
	or	al,al
	jne	ihypk050			; yes
	jmp	ihypk950			; no

ihypk050:
	mov	es,DOT_SEG
	inc	HYPER_KLN_FLAG
	cmp	al,32				; half way done ?
	jne	ihypk300
	mov	si,2*32
	mov	cx,32
ihypk100:
	neg	TITLE_X_VEL[si]			; cause drift toward final destination
	neg	TITLE_Y_VEL[si]
	inc	si
	inc	si
	loop	ihypk100
	jmp	ihypk320

ihypk300:
	cmp	al,64				; fully done ?
	jne	ihypk320			; no
	jmp	ihypk900			; yes

ihypk320:
	mov	si,2*32
	mov	cx,32
ihypk400:
	mov	bx,TITLE_X_DIS[si]		; erase old pixel
	mov	dx,TITLE_Y_DIS[si]
	call	Pixel

	mov	ax,TITLE_X_VEL[si]		; calc new pixel position
	cwd
	shl	ax,1
	rcl	dx,1				; scale up by two
	add	ax,XVELL+KLNOBJ			; make total velocity
	adc	dx,XVEL+KLNOBJ

	add	TITLE_X_DISL[si],ax
	adc	dx,TITLE_X_DIS[si]
	jns	ihypk410			; screen wrap
	add	dx,MAX_X_AXIS
	jmp	ihypk420
ihypk410:
	cmp	dx,MAX_X_AXIS
	jb	ihypk420
	sub	dx,MAX_X_AXIS
ihypk420:
	mov	TITLE_X_DIS[si],dx
	mov	bx,dx				; for draw pixel later

	mov	ax,TITLE_Y_VEL[si]		; calc new pixel position
	cwd
	shl	ax,1
	rcl	dx,1				; scale up by two
	shl	ax,1
	rcl	dx,1				; scale up by two
	add	ax,YVELL+KLNOBJ			; make total velocity
	adc	dx,YVEL+KLNOBJ

	add	TITLE_Y_DISL[si],ax
	adc	dx,TITLE_Y_DIS[si]
	jns	ihypk510			; screen wrap
	add	dx,MAX_Y_AXIS
	jmp	ihypk520
ihypk510:
	cmp	dx,MAX_Y_AXIS
	jb	ihypk520
	sub	dx,MAX_Y_AXIS
ihypk520:
	mov	TITLE_Y_DIS[si],dx
	call	Pixel				; draw pixel in new position
	inc	si
	inc	si
	loop	ihypk400

	jmp	ihypk950

ihypk900:					; done with hyperspace
	mov	si,2*32
	mov	cx,32
ihypk930:
	mov	bx,TITLE_X_DIS[si]		; erase all pixels
	mov	dx,TITLE_Y_DIS[si]
	call	Pixel
	inc	si
	inc	si
	loop	ihypk930

	mov	HYPER_KLN_FLAG,0		; stop hyperspace
	or	byte ptr UFLG+KLNOBJ,BIT0	; flag for an update
	or	byte ptr EFLG+KLNOBJ,BIT0	; enable klingon, should draw it
	mov	ax,TITLE_X_DIS+2*32
	mov	XDIS+KLNOBJ,ax
	mov	XDRAWN+KLNOBJ,ax		; new position
	mov	ax,TITLE_Y_DIS+2*32
	mov	YDIS+KLNOBJ,ax
	mov	YDRAWN+KLNOBJ,ax
	xor	ax,ax
	mov	XVEL+KLNOBJ,ax			; stop klingon
	mov	XVELL+KLNOBJ,ax
	mov	YVEL+KLNOBJ,ax
	mov	YVELL+KLNOBJ,ax
	mov	XDISL+KLNOBJ,ax
	mov	YDISL+KLNOBJ,ax

	and	SOUND_FLAG,NOT HYPER_SOUND	; stop sound
ihypk950:					; no hyperspace for klingon

;	****** NEXT PLANET STATE ******

	mov	al,BLINK
	and	al,PLANET_TIME-1
	jne	pstate

	test	PLANET_ENABLE,BIT0		; display PLANET ?
	je	pstate				; NO
	inc	PLANET_STATE			; new state
	mov	al,PLANET_STATE
	mov	bx,PLANET_X			; center of the screen
	mov	dx,PLANET_Y
	call	Draw_The_Planet

pstate:
	mov	al,20h				; send non-specific EOI to PIC
	out	INTA00,al

	pop	es
	pop	ds
	pop	bp
	pop	di
	pop	si
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	iret

Play_Interrupt	endp

space_code	ends
	end
